package com.zzwx.controller.context;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.zzwx.common.constant.Constants;
import com.zzwx.common.dto.Page;
import com.zzwx.common.utils.CommonUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Aspect
@Component
public class AOPAdvice {
	private static final Logger logger = LoggerFactory
			.getLogger(AOPAdvice.class);
	public static final Gson gsonDate = new GsonBuilder().setDateFormat(
			Constants.DATE_TIME_PATTERN).create();

	@Pointcut("execution(public * com.zzwx.controller.sys.*.*(..))")
	private void outputLogMethod1() {
	}

	/**
	 * Before 在核心业务执行前执行，不能阻止核心业务的调用。
	 * 
	 * @param joinPoint
	 */
	@Before("outputLogMethod1()")
	public void beforeAdvice(JoinPoint joinPoint) {
		if (!joinPoint.getSignature().getName().equals("initBinder")) {
			try {
				Object[] params = joinPoint.getArgs();
				if (null != params && params.length > 0) {
					StringBuilder sb = new StringBuilder();
					sb.append(String.format("Method:[%s.%s()]", joinPoint
							.getSignature().getDeclaringTypeName(), joinPoint
							.getSignature().getName()));

					for (int i = 0; i < params.length; i++) {
						Object param = params[i];
						if (null != param) {
							if (!CommonUtil.isBaseType(param)
									&& !(param instanceof HttpServletRequest)
									&& !(param instanceof HttpServletResponse)) {
								sb.append(String.format("Params:[%s]", i));
								sb.append(String.format("[%s]", param
										.getClass().getName()));
								sb.append("--->")
										.append(gsonDate.toJson(param));
							} else {
								sb.append(String.format("Params:[%s]", i));
								sb.append("--->").append(param);
							}
						} else
							logger.info("请求参数：无");
					}
					logger.info(sb.toString());
				} else {
					logger.info("请求参数：无");
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
	}

	/**
	 * Around 手动控制调用核心业务逻辑，以及调用前和调用后的处理,
	 * 
	 * 注意：当核心业务抛异常后，立即退出，转向AfterAdvice 执行完AfterAdvice，再转到ThrowingAdvice
	 * 
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
	@Around(value = "outputLogMethod1()")
	public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
		// 调用核心逻辑
		Object retVal = pjp.proceed();
		try {
			String str = "";
			if (CommonUtil.isNotEmpty(retVal)) {
				if (retVal instanceof Page<?>
						|| retVal instanceof ResponseEntity<?>) {
					str = gsonDate.toJson(retVal);
				} else {
					str = retVal.toString();
				}
				logger.info("返回数据  : " + str);
			} else {
				logger.info("返回类型是 Void");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return retVal;
	}
}